from sls_uavDialog import Ui_UAVDialog
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                            QHBoxLayout, QPushButton, QLineEdit, QListWidget, 
                            QLabel, QMessageBox,QDialog)
from PyQt6.QtCore import Qt

from sls_ngc_uavPPDialog import UAVPPDialog

from sls_mirrors import sls_UGVmirrorsUpdate,sls_agent,sls_UAVmirrorsUpdate
from sls_uavNormalMissions.sls_uavNormalMissions import missions_table

import time
import os

class UAVDialog(QDialog):
    def __init__(self, parent, id:str,button:QPushButton):
        super().__init__(parent)
        self.id = id
        self.parent = parent
        self.button = button
        self.button.setEnabled(False)
        self.polylines = []
        self.trajectory = []
        self.last_position = None
        self.real_path_points = []
        self.path_shown_flag = False
        self.record_path_flag =False
        self.old_is_flying = False
        self.mirror_agent = self.parent.mirror_agent
        self.notifyClass = self.parent.notifyClass
        self.mirror_agent:sls_agent.MirrorsAgent
        self.mirror_agent.add_notify_func_to_mirror_update(id,sls_UAVmirrorsUpdate.BasicPositionMirrorUpdate,self.showUAVPosition)
        self.mirror_agent.add_notify_func_to_mirror_update(id,sls_UAVmirrorsUpdate.BasicStatusMirrorUpdate,self.showandSaveRealPath)
        self.mirror_agent.add_notify_func_to_schedule_update(id,"missionsList",self.showMSMissionList)
        self.mirror_agent.add_notify_func_to_schedule_update(id,"runingTask",self.showMSRuningTask)
        self.mirror_agent.add_notify_func_to_schedule_update(id,"missionStatus",self.showMStatus)
        # 初始化UI
        self.ui = Ui_UAVDialog()
        self.ui.setupUi(self)
        self.setWindowTitle(f"{self.id}的信息")
        self.comboBoxInit()

        # 连接按钮点击事件更新任务列表
        self.ui.updateListButton.clicked.connect(self.updateListButtonClicked)
        #双击任务列表，显示任务详情
        self.ui.listWidget.itemDoubleClicked.connect(self.show_mission_data)
        #开始任务
        self.ui.startMSButton.clicked.connect(lambda: self.mirror_agent.start_mission_schedule(self.id))
        #停止任务
        self.ui.stopMSButton.clicked.connect(lambda: self.mirror_agent.stop_mission_schedule(self.id))
        #重启任务
        self.ui.restartMSButton.clicked.connect(lambda: self.mirror_agent.restart_mission_schedule(self.id))
        #添加常规任务到指定index
        self.ui.addMissionButton.clicked.connect(self.addMissionButtonClicked)
        #添加任务按钮
        self.ui.appendMissionButton.clicked.connect(self.appendMissionButtonClicked)
        #删除选择的任务按钮
        self.ui.delSelMissionButton.clicked.connect(self.delSelMissionButtonClicked)
        #删除最后的任务按钮
        self.ui.delLastMissionButton.clicked.connect(self.delLastMissionButtonClicked)
        #moveup mission
        self.ui.moveUpMissionButton.clicked.connect(self.moveUpMissionButtonClicked)
        #movedown mission
        self.ui.moveDownMissionButton.clicked.connect(self.moveDownMissionButtonClicked)
        #显示路径的按钮
        self.ui.showPathButton.clicked.connect(self.showPathButtonClicked)

        #更新任务列表
        self.mirror_agent.request_scheduleUpdate_missions_list(self.id)

    def comboBoxInit(self):
        for item in missions_table:
            self.ui.comboBox.addItem(item)

    def closeEvent(self, event):
        # 当对话框关闭时，重新启用父窗口的按钮
        self.close_callback()


    def showUAVPosition(self,mirror,basicStatus:sls_UAVmirrorsUpdate.BasicPositionMirrorUpdate):
        GNSS_position = basicStatus.GNSS_position
        latitude = GNSS_position["latitude"]
        longitude = GNSS_position["longitude"]
        self.latitude = latitude
        self.longitude = longitude
        if self.record_path_flag:
            self.real_path_points.append([longitude,latitude])
        if self.path_shown_flag:
            point = [longitude,latitude]
            self.parent.append_point_polyline(self.id+"trajectroy",point)
        vehicle_yaw = basicStatus.vehicle_yaw
        rel_alt = basicStatus.rel_alt
        self.trajectory.append([longitude,latitude])
        self.ui.longitudeLabel.setText(f"{longitude:.6f}")
        self.ui.latitudeLabel.setText(f"{latitude:.6f}")
        if rel_alt is None:
            rel_alt = 0.0
        self.ui.altitudeLabel.setText(f"{rel_alt:.2f}")

    
    def showMSMissionList(self,mirror, scheduleUpdate:sls_agent.ScheduleUpdate):
        self.ui.listWidget.clear()
        for index, mission in enumerate(scheduleUpdate.missionsList):
            self.ui.listWidget.addItem(f"任务{index}: {mission['missionsType']}")

    def showMSRuningTask(self,mirror, scheduleUpdate:sls_agent.ScheduleUpdate):
        runingTask = scheduleUpdate.runingTask
        tostr = str(runingTask["datasets"])
        tostrlen = len(tostr)
        first_40 = tostr[:40]
        if (tostrlen<41):
            self.ui.currentMissionLabel.setText(f"当前任务类型: {runingTask['missionsType']}\n当前任务数据: {runingTask['datasets']}")
        else:
            self.ui.currentMissionLabel.setText(f"当前任务类型: {runingTask['missionsType']}\n当前任务数据: {first_40}......")
    
    def showMStatus(self,mirror, scheduleUpdate:sls_agent.ScheduleUpdate):
        missionStatus = scheduleUpdate.missionStatus
        self.ui.missionStatusLabel.setText(f"任务状态: {missionStatus['status']}任务索引: {missionStatus['index']}")

    def updateListButtonClicked(self):
        self.ui.listWidget.clear()
        self.mirror_agent.request_scheduleUpdate_missions_list(self.id)

    def show_mission_data(self,item):
        #根据现在listWidget的选中项，显示任务数据
        #获取选中项的索引
        mirror =self.mirror_agent.find_mirror_by_id(self.id)
        for index, mission in enumerate(mirror.scheduleUpdate.missionsList):
            #找到当前选中的mirro
            if index == self.ui.listWidget.currentRow():
                datasets = mission["datasets"]
                missionsType = mission["missionsType"]
                self.ui.missionDataLabel.setText(f"任务类型: {missionsType}\n数据: {datasets}")

    def addMissionButtonClicked(self):
        #获取当前选中的任务类型
        missionsType = self.ui.comboBox.currentText()
        if missionsType == "MissionsQRLand":
            self.missionWindow = missions_table[missionsType](self,index=self.ui.listWidget.currentRow())
        else:
            #获取当前选中的任务索引
            self.missionWindow = missions_table[missionsType](self,index=self.ui.listWidget.currentRow())
            self.missionWindow.move(1150,150)
            self.missionWindow.show()

    def appendMissionButtonClicked(self):
        #获取当前选中的任务类型
        missionsType = self.ui.comboBox.currentText()   
        self.missionWindow = missions_table[missionsType](self,index=-1)
        self.missionWindow.show()
    
    def delSelMissionButtonClicked(self):
        #获取当前选中的任务索引
        self.mirror_agent.delete_mission_from_schedule(self.id,self.ui.listWidget.currentRow())
        #更新任务列表
        self.mirror_agent.request_scheduleUpdate_missions_list(self.id)

    def delLastMissionButtonClicked(self):
        #获取当前选中的任务索引
        self.mirror_agent.delete_mission_from_schedule(self.id,-1)
        #更新任务列表
        self.mirror_agent.request_scheduleUpdate_missions_list(self.id)
        for name in self.polylines:
            self.parent.del_polyline(name)
        self.polylines = []
        self.path_shown_flag = False
        self.showPathButtonClicked()
    
    def showPathButtonClicked(self):
        if self.path_shown_flag:
            for name in self.polylines:
                self.parent.del_polyline(name)
                self.polylines = []
                self.last_position = None
                self.trajectory = []
                self.path_shown_flag = False
        else :
            #获取任务列表
            missions_list = self.mirror_agent.get_missons_list_from_schedule(self.id)
            #获取所有任务的路径，路径存在datasets中，格式为{"latitudes":[47.3978,47.3878],"longitudes":[8.5461,8.5361],"boundaries":{"latitudes":[],"longitudes":[]}}
            latitudes = []
            longitudes = []
            for mission in missions_list:
                if mission["datasets"]:
                    datasets = mission["datasets"]
                #判断有没有latitudes和longitudes,latitude,longitude
                    if "latitudes" in datasets or "longitudes" in datasets:
                        latitudes.extend(datasets["latitudes"])
                        longitudes.extend(datasets["longitudes"])
                    if 'latitude' in datasets and 'longitude' in datasets:
                        latitudes.append(datasets["latitude"])
                        longitudes.append(datasets["longitude"])
                    #获取边界
                    if "boundaries" in datasets:
                        boundaries = datasets["boundaries"]
                        boundaris_latitudes=boundaries["latitudes"]
                        boundaris_longitudes=boundaries["longitudes"]
                        #绘制边界
                        color = "#3010A3"
                        self.parent.del_polyline("show"+self.id+"boundary*"+str(missions_list.index(mission)))
                        if boundaris_latitudes+[boundaris_latitudes[0]] and boundaris_longitudes+[boundaris_longitudes[0]] :
                            self.parent.add_polyline_lat_lon(boundaris_latitudes+[boundaris_latitudes[0]],boundaris_longitudes+[boundaris_longitudes[0]],color,"show"+self.id+"boundary*"+str(missions_list.index(mission)))
                            self.polylines.append("show"+self.id+"boundary*"+str(missions_list.index(mission)))
            #绘制路径
            color = "#E20D29"
            if latitudes and longitudes:
                self.parent.add_polyline_lat_lon(latitudes,longitudes,color,"show"+self.id+"path")
                self.polylines.append("show"+self.id+"path")
            if len(self.real_path_points) == 0:
                trajectory = [[self.longitude,self.latitude]]
            else:
                trajectory = self.real_path_points
            color = "#3010A3"
            if trajectory:
                self.parent.add_polyline(trajectory,color,self.id+"trajectroy")
                self.polylines.append(self.id+"trajectroy")
            self.path_shown_flag = True
    
    def showandSaveRealPath(self,mirror,basicStatus:sls_UAVmirrorsUpdate.BasicStatusMirrorUpdate):
        if basicStatus.is_flying:
            if self.old_is_flying == False:
                #start  fly
                self.record_path_flag = True
                #create a file and file name has time
                #get year month day hour minute
                timestr = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime())
                #file path is in relative path recordedPath
                recorded_path = os.path.join(os.getcwd(), "recordedPath")
                #if recordedPath not exist, create it
                if not os.path.exists(recorded_path):
                    os.makedirs(recorded_path)
                file_path = os.path.join(recorded_path, "path_"+self.id+timestr+".csv")
                self.path_file = open(file_path,"w")
        else:
            if self.old_is_flying == True:
                #stop fly
                self.record_path_flag = False
                #write self.real_path_points as a csv to file self.path_file
                for point in self.real_path_points:
                    self.path_file.write(str(point[0])+","+str(point[1])+",")           
                #close file
                self.path_file.close()
                self.real_path_points.clear()
        
        self.old_is_flying = basicStatus.is_flying             

    def moveUpMissionButtonClicked(self):
        self.mirror_agent.moveup_mission_in_schedule(self.id,self.ui.listWidget.currentRow())
        #更新任务列表
        self.mirror_agent.request_scheduleUpdate_missions_list(self.id)
    
    def moveDownMissionButtonClicked(self):
        self.mirror_agent.movedown_mission_in_schedule(self.id,self.ui.listWidget.currentRow())
        #更新任务列表
        self.mirror_agent.request_scheduleUpdate_missions_list(self.id)

    def keyPressEvent(self, event):
        # 检测是否按下 ESC 键
        if event.key() == Qt.Key.Key_Escape:
            self.close_callback()  # 关闭窗口
        # 记得调用父类的方法以确保其他键盘事件正常处理
        super().keyPressEvent(event)    

    def close_callback(self):
        for name in self.polylines:
            self.parent.del_polyline(name)
        self.polylines.clear()
        self.mirror_agent.remove_notify_func_from_mirror_update(self.id,sls_UAVmirrorsUpdate.BasicPositionMirrorUpdate,self.showUAVPosition)
        self.mirror_agent.remove_notify_func_from_mirror_update(self.id,sls_UAVmirrorsUpdate.BasicStatusMirrorUpdate,self.showandSaveRealPath)
        self.mirror_agent.remove_notify_func_from_schedule_update(self.id,"missionsList",self.showMSMissionList)
        self.mirror_agent.remove_notify_func_from_schedule_update(self.id,"runingTask",self.showMSRuningTask)
        self.mirror_agent.remove_notify_func_from_schedule_update(self.id,"missionStatus",self.showMStatus)
        self.button.setEnabled(True)
